package com.wodsy.phoenix.datadao.base;

import com.wodsy.phoenix.dataobject.base.Pager;
import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.cache.annotation.CacheEvict;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class BaseHibernateDao<M extends Serializable, PK extends Serializable>{
    protected  Logger logger = Logger.getLogger(this.getClass());



	protected SessionFactory sessionFactory;

    public abstract void setSessionFactory(SessionFactory sessionFactory) ;

    public SessionFactory getSessionFactory() {
		return sessionFactory;
	}

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * 分页
	 * 
	 * @param pager
	 * @param criteria
	 */
	protected void pageFor(Pager<M> pager, Criteria criteria) {
		if (pager.getPageNo() != null) {
			pager.setPageNo(pager.getPageNo());
//			pager.setPageSize(10);
			Integer totalCount = pager.getTotalCount();
			if(pager.getTotalCount()==null)
				totalCount = ((Long) criteria.setProjection(
						Projections.rowCount()).uniqueResult()).intValue();
			criteria.setProjection(null);
			pager.setTotalCount(totalCount);// 总记录数

			// 总页数
			if (totalCount % pager.getPageSize() == 0) {
				pager.setTotalPage(totalCount / pager.getPageSize());
			} else {
				pager.setTotalPage(totalCount / pager.getPageSize() + 1);
			}
			criteria.setFirstResult((pager.getPageNo() - 1)
					* pager.getPageSize());
			criteria.setMaxResults(pager.getPageSize());
		}
	}

	public M get(PK pk) {
		return (M) (getSession().get(getModelClass(), pk));
	}
	@CacheEvict(value="commonCache",allEntries=true)
	public void save(M obj) {
		getSession().save(obj);
	}
	@CacheEvict(value="commonCache",allEntries=true)
	public void delete(M obj) {
		getSession().delete(obj);
	}
	@CacheEvict(value="commonCache",allEntries=true)
	public void update(M obj) {
		getSession().update(obj);
	}
	@CacheEvict(value="commonCache",allEntries=true)
	public void merge(M obj) {
		getSession().merge(obj);
	}
	public void saveOrUpdate(M obj){
		getSession().saveOrUpdate(obj);
	}

	public List<M> findByAll(){
		List<M> list = getSession().createCriteria(getModelClass()).list();
		return list;
	}
	
	public M findByProperty(String propertyName, Object value) {
		M m = (M) getSession().createCriteria(getModelClass())
				.add(Restrictions.eq(propertyName, value))
				.uniqueResult();
		
		return m;
	}
	
	public List<M> findAllByProperty(String propertyName,Object value) {
		return getSession().createCriteria(getModelClass())
				.add(Restrictions.eq(propertyName, value))
				.list();
	}
	
	
	/**
	 * 分页
	 * @param pager
	 * @param criteria
	 * @author zhaosy
	 * @date 2012-08-31 13:22:55
	 */
	protected Pager<M> toPager(Pager<M> pager, Criteria criteria) {
		Integer totalCount = pager.getTotalCount();
		if(pager.getTotalCount()==null||pager.getTotalCount()==0){
			Object obj	= criteria.setProjection(Projections.rowCount()).uniqueResult();
			if(obj!=null)
				totalCount = ((Long)obj).intValue();
		}
		criteria.setProjection(null);
		pager.setTotalCount(totalCount);// 总记录数
		//
		if(pager.getPageNo()==null||pager.getPageNo()==0){
			pager.setPageNo(1);
		}
		if(pager.getPageSize()!=null&&pager.getPageSize()>0){
			pager.setPageSize(pager.getPageSize());
		}else{
			pager.setPageSize(10);
		}
		criteria.setFirstResult((pager.getPageNo() - 1)
				* pager.getPageSize());
		criteria.setMaxResults(pager.getPageSize());
		criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		pager.setItems(criteria.list());

		// 总页数
		if (totalCount % pager.getPageSize() == 0) {
			pager.setTotalPage(totalCount / pager.getPageSize());
		} else {
			pager.setTotalPage(totalCount / pager.getPageSize() + 1);
		}
		//下一页
		if((pager.getPageNo()+1)>=pager.getTotalPage()){
			pager.setNextPageNo(pager.getTotalPage());
		}else {
			pager.setNextPageNo(pager.getPageNo()+1);
		}
		//上一页
		if(pager.getPageNo()-1<=0){
			pager.setPrevPageNo(1);
		}else {
			pager.setPrevPageNo(pager.getPageNo()-1);
		}
		return pager;
	}
	
	/**
	 * 分页SQL
	 * @param pager
	 * @param sql
	 * @author zhaosy
	 * @date 2012-08-31 13:22:55
	 */
	protected Pager<Map<String, String>> toPagerBySql(Pager<Map<String, String>> pager, String sql) {
			if(pager.getPageNo()==null||pager.getPageNo()==0){
				pager.setPageNo(1);
			} 
			if(pager.getPageSize()!=null&&pager.getPageSize()>0){
				pager.setPageSize(pager.getPageSize());
			}else{
				pager.setPageSize(10);
			}
			
			SQLQuery  query = getSession().createSQLQuery(sql+" limit "+(pager.getPageNo() - 1)
						* pager.getPageSize()+" , "+pager.getPageSize());
			
			List<Map<String,String>> list = new ArrayList<>();
			List<Object[]> queryList = query.list();
			Object[] objNames = getReturnAliases(sql);
			for (int i = 0,k = queryList.size(); i < k; i++) {
				Map<String, String> map = new HashMap<>();
				Object[] objs = queryList.get(i);
					for (int j = 0; j < objNames.length; j++) {
						map.put(sqlToJavaStyle(objNames[j].toString()), objs[j]==null?"":objs[j].toString());
					}
					list.add(map);
					
			}
			pager.setItems(list);
			
			Integer totalCount = pager.getTotalCount();
			if(pager.getTotalCount()==null||pager.getTotalCount()==0){
				totalCount = getAllCount(sql);
			}
			
			pager.setTotalCount(totalCount);// 总记录数

			// 总页数
			if (totalCount % pager.getPageSize() == 0) {
				pager.setTotalPage(totalCount / pager.getPageSize());
			} else {
				pager.setTotalPage(totalCount / pager.getPageSize() + 1);
			}
			//下一页
			if((pager.getPageNo()+1)>=pager.getTotalPage()){
				pager.setNextPageNo(pager.getTotalPage());
			}else {
				pager.setNextPageNo(pager.getPageNo()+1);
			}
			//上一页
			if(pager.getPageNo()-1<=0){
				pager.setPrevPageNo(1);
			}else {
				pager.setPrevPageNo(pager.getPageNo()-1);
			}
		return pager;
	}
	
	
	private String sqlToJavaStyle(String str){
		int leng = str.split("_").length;
		String[] arr = str.split("_");
		String string = null;
		if(leng>0){
			for (int i = 0; i < leng; i++) {
				if(i==0){
					str = arr[i];
				}else {
					string = arr[i];
					str += string.substring(0,1).toUpperCase()+string.substring(1,string.length());
				}
				
			}
		}
		return str;
	}
	
	protected int getAllCount(String sql){
		
		String[] fromNo  = sql.toLowerCase().split("from");
	
		if(fromNo.length>2){//郝瑞龙修改--大于2了 就用小写分割
			sql = sql.split("from")[1];
		}else {
			sql = sql.toLowerCase().split("from")[1];
		}
		if(sql.toLowerCase().indexOf("group by")!=-1){//蒋少波修改
			sql = sql.substring(0,sql.toLowerCase().indexOf("group by"));
		}

		
		@SuppressWarnings("unchecked")
        List<BigInteger[]> query = getSession().createSQLQuery("select count(*) num from "+sql).list();
		if(query!=null&&query.size()>0){
			Object objs = query.get(0);
			return Integer.parseInt(objs == null ? "0" : objs.toString());
		} 
		return 0 ;
	}
	
	/**按时间去重**/
	protected int getDistinctAllCount(String sql){
		
		String[] fromNo  = sql.toLowerCase().split("from");
	
		if(fromNo.length>2){//
			sql = sql.split("from")[1];
		}else {
			sql = sql.toLowerCase().split("from")[1];
		}

			if(sql.toLowerCase().indexOf("group by")!=-1){//蒋少波修改
				String count = "";
				if(sql.toLowerCase().indexOf("order by")!=-1){
					count = sql.substring(sql.toLowerCase().indexOf("group by ")+8,sql.toLowerCase().indexOf("order by"));
				}else{
					count = sql.substring(sql.toLowerCase().indexOf("group by ")+8);
				}
			sql = sql.substring(0,sql.toLowerCase().indexOf("group by"));
			sql = "select count(DISTINCT "+count+") from " +sql;
		}else{
			sql = "select count(*) from "+sql;
		}

		
        List<BigInteger[]> query = getSession().createSQLQuery(sql).list();
		if(query!=null&&query.size()>0){
			Object objs = query.get(0);
			return Integer.parseInt(objs == null ? "0" : objs.toString());
		} 
		return 0 ;
	}
	
	private Object[] getReturnAliases(String sql){
		sql = sql.toLowerCase().split("from")[0];
		sql = sql.replace("select","");
		sql = sql.replace(" ","");
		String[] strings = sql.split(",");
		List<String> list = new ArrayList<String>();
		for (int i = 0; i < strings.length; i++) {
			if(strings[i]!=null&&!"".equals(strings[i])&&!"".equals(strings[i].trim())){
				if(strings[i].indexOf(".")==-1){
					list.add(strings[i]);
				}else {
					list.add(strings[i].split("\\.")[1]);
				}
				
			}
		}
		return list.toArray();
	}

	public abstract Class<M> getModelClass();
}
